package com.heima.wemedia.service.impl;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.api.R;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.apis.article.IArticleClient;
import com.heima.apis.schedule.IScheduleClient;
import com.heima.model.article.dtos.ArticleDto;
import com.heima.model.common.dtos.PageResponseResult;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.schedule.dto.Task;
import com.heima.model.wemedia.dtos.NewsAuthDto;
import com.heima.model.wemedia.dtos.WmNewsDto;
import com.heima.model.wemedia.dtos.WmNewsPageReqDto;
import com.heima.model.wemedia.pojos.*;
import com.heima.model.wemedia.vo.WmNewsVo;
import com.heima.utils.ProtostuffUtil;
import com.heima.wemedia.mapper.*;
import com.heima.wemedia.service.AutoScanService;
import com.heima.wemedia.service.WmNewsService;
import com.heima.wemedia.thread.UserThreadLocal;
import io.jsonwebtoken.lang.Collections;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

@Service
@Slf4j
@Transactional
public class WmNewsServiceImpl  extends ServiceImpl<WmNewsMapper, WmNews> implements WmNewsService {

    @Autowired
    private WmNewsMapper wmNewsMapper;
    @Autowired
    private WmMaterialMapper wmMaterialMapper;
    @Autowired
    private WmNewsMaterialMapper wmNewsMaterialMapper;
    @Autowired
    private AutoScanService autoScanService;
    @Autowired
    private IScheduleClient scheduleClient;
    @Autowired
    private IArticleClient iArticleClient;
    @Autowired
    private KafkaTemplate kafkaTemplate;
    @Autowired
    private WmUserMapper wmUserMapper;
    @Autowired
    private WmChannelMapper wmChannelMapper;
    @Override
    public ResponseResult newsList(WmNewsPageReqDto dto) {
        if (dto==null) {
            return new PageResponseResult(0,0,0);
        }
        Short status = dto.getStatus();
        Date beginPubDate = dto.getBeginPubDate();
        Date endPubDate = dto.getEndPubDate();
        Integer channelId = dto.getChannelId();
        String keyword = dto.getKeyword();
        Integer dtoSize = dto.getSize();
        Integer dtoPage = dto.getPage();
        //1.构建查询条件
        LambdaQueryWrapper<WmNews> wrapper = new LambdaQueryWrapper<>();
        //状态查询
        wrapper.eq(status!=null,WmNews::getStatus,status);
        //发布时间范围
        wrapper.between(beginPubDate!=null&&endPubDate!=null,WmNews::getPublishTime,beginPubDate,endPubDate);
        //频道查询
        wrapper.eq(channelId!=null,WmNews::getChannelId,channelId);
        //关键字(模糊查询)
        wrapper.like(StringUtils.isEmpty(keyword),WmNews::getTitle,keyword);
        //查询当前用户的文章
        wrapper.eq(WmNews::getUserId, UserThreadLocal.get().getId());
        //2.添加排序条件
        wrapper.orderByDesc(WmNews::getPublishTime);
        //3.构建分页条件
        Page<WmNews> page = new Page<>(dtoPage,dtoSize);
        //4.执行分页查询
        Page<WmNews> wmNewsPageResult= wmNewsMapper.selectPage(page, wrapper);
        //5.构建返回值并返回
        PageResponseResult pageResponseResult = new PageResponseResult(dtoPage,dtoSize, (int) wmNewsPageResult.getTotal());
        pageResponseResult.setData(wmNewsPageResult.getRecords());
        return pageResponseResult;
    }

    @Override
    @Transactional(rollbackFor =RuntimeException.class )
    public ResponseResult submit(WmNewsDto wmNewsDto) {
        //1.提取新闻内容
        WmNews wmNews = wmNewsDto2WmNews(wmNewsDto);
        if (wmNews==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //2.插入新闻表
        int insertResult = wmNewsMapper.insert(wmNews);
        if(insertResult<1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR);
        }
        //3.判断是不是草稿(是则返回)
        Short status = wmNewsDto.getStatus();
        if (status==0) {
            return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
        }
        //4.提取新闻图片(素材)
        //4.1内容图
        String content = wmNewsDto.getContent();
        List<String> contentImages = getContentImages(content);
        //4.2封面图
        Short type = wmNewsDto.getType();
        List<String> images = wmNewsDto.getImages();
        //5.如果是自动布局,要到内容图中,提取图片作为封面图
        List<String> coverImages = getCoverImages(type, images, contentImages);
        //6.素材添加
        Boolean contentImageResult = addMaterial(wmNews.getId(), contentImages, 0);
        if(!contentImageResult){
            throw new RuntimeException("内容图添加失败");
        }
        //7.素材和新闻类关系添加
        Boolean coverImageResult = addMaterial(wmNews.getId(), coverImages, 1);
        if(!coverImageResult){
            throw new RuntimeException("封面图添加失败");
        }
        //8.调用审核代码
//        try {
//            autoScanService.autoScanWmNews(wmNews.getId().longValue());
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        Boolean addTaskResult = addToTask(wmNews.getId(), wmNews.getPublishTime().getTime());
        if (!addTaskResult) {
            throw new RuntimeException("任务添加失败");
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Override
    public ResponseResult downOrUp(WmNewsDto wmNewsDto) {
        //0.判断入参是否为空
        if (wmNewsDto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //1.查新闻
        Integer newsId = wmNewsDto.getId();
        if (newsId==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        WmNews wmNews = wmNewsMapper.selectById(newsId);
        if (wmNews==null) {
            log.warn("新闻不存在");
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }
        //2.新闻是否发布
        Short status = wmNews.getStatus();
        if(!(status==9)){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"新闻未发布");
        }
        //3.更新enable字段
        Short enable = wmNewsDto.getEnable();
        wmNews.setEnable(enable);
        int updateResult = wmNewsMapper.updateById(wmNews);
        if(updateResult<1){
            log.warn("新闻更新失败");
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"新闻更新失败");
        }
        //4.kafaka发送信息
//        Map<String, Object> map = new HashMap<>();
//        map.put("articleId",wmNews.getArticleId());
//        map.put("enable",wmNews.getEnable());
//        kafkaTemplate.send("news.down.up.topic",JSON.toJSONString(map));
        kafkaTemplate.send("news.down.up.topic",JSON.toJSONString(wmNews));

        return ResponseResult.okResult("");
    }

    @Override
    public ResponseResult findList(NewsAuthDto newsAuthDto) {
        //0.参数判空
        if (newsAuthDto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //1.参数检查
        newsAuthDto.checkParam();
        Integer currentPage = newsAuthDto.getPage();
        Integer page = newsAuthDto.getPage();
        Integer size = newsAuthDto.getSize();
        //2.分页查询+count查询
        newsAuthDto.setPage((page-1)*size);
        List<WmNewsVo> wmNewsVoList=wmNewsMapper.findList(newsAuthDto);
        int count =wmNewsMapper.findListCount(newsAuthDto);

        //4.结果返回
        PageResponseResult pageResponseResult = new PageResponseResult(currentPage, size, count);
        pageResponseResult.setData(wmNewsVoList);
        return pageResponseResult;
    }

    @Override
    public ResponseResult findWmNewsVo(Integer id) {
        //0.参数判空
        if(id==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //1.根据id查询WmNews
        WmNews wmNews = wmNewsMapper.selectById(id);
        if(wmNews==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //2.根据wmNews.getUserId 获取wmUser信息
        Integer userId = wmNews.getUserId();
        WmUser wmUser = wmUserMapper.selectById(userId);
        if(wmUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //3.组合并返回
        WmNewsVo wmNewsVo = new WmNewsVo();
        BeanUtils.copyProperties(wmNews,wmNewsVo);
        if(wmNewsVo!=null){
            wmNewsVo.setAuthorName(wmUser.getName());
        }
        return ResponseResult.okResult(wmNewsVo);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ResponseResult passOrFail(NewsAuthDto newsAuthDto, Integer type) {
        //0.参数判空
        if (newsAuthDto==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        //1.修改状态和信息
        Integer id = newsAuthDto.getId();
        String msg = newsAuthDto.getMsg();
        int status =type==1?9:2;//9通过,2未通过
        WmNews wmNews = wmNewsMapper.selectById(id);
        if (wmNews==null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"新闻不存在");
        }
        wmNews.setStatus((short)status);
        wmNews.setReason(type==1?"通过":msg);
        int updateResult = wmNewsMapper.updateById(wmNews);
        if(updateResult<1){
            return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR,"新闻审核失败");
        }
        //2.通过则保存
        if(type==1){
            ArticleDto dto=wmNews2ArticleDto(wmNews);
            ResponseResult responseResult = iArticleClient.saveArticle(dto);
            if(responseResult==null||responseResult.getCode()!=200){
                throw new RuntimeException("文章保存失败");
            }
        }
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    public Boolean addToTask(Integer newsId,Long executeTime){
        Task task = new Task();
        task.setExecuteTime(executeTime);
        WmNews wmNews = new WmNews();
        wmNews.setId(newsId);
        byte[] bytes = ProtostuffUtil.serialize(wmNews);
        task.setParameters(bytes);
        ResponseResult responseResult = scheduleClient.addTask(task);
        if (responseResult!=null&&responseResult.getCode()!=200) {
            return true;
        }
        return false;
    }

    public WmNews wmNewsDto2WmNews(WmNewsDto wmNewsDto){
        if (wmNewsDto==null) {
            return null;
        }
        WmNews wmNews = new WmNews();
        //自动映射
        BeanUtils.copyProperties(wmNewsDto,wmNews);
        //处理额外字段
        wmNews.setId(UserThreadLocal.get().getId());
        if (wmNews.getType()==-1) {
            wmNews.setType(null);
        }
        wmNews.setCreatedTime(new Date());
        wmNews.setEnable((short) 1);
        List<String> images = wmNewsDto.getImages();
        if (!Collections.isEmpty(images)) {
            String join = StringUtils.join(images, ",");
            wmNews.setImages(join);
        }
        return wmNews;
    }

    private List<String> getContentImages(String content){
        if (StringUtils.isEmpty(content)) {
            return new ArrayList<>();
        }
        ArrayList<String> urlList = new ArrayList<>();
        //1.将content转为集合
        List<Map> maps = JSON.parseArray(content, Map.class);
        if (CollectionUtils.isEmpty(maps)) {
            return new ArrayList<>();
        }
        //2.遍历
        for (Map item : maps) {
            if (CollectionUtils.isEmpty(item)) {
                continue;
            }
            //3.判断type=image
            Object type = item.get("type");
            if ("image".equals(type)) {
                String value = (String) item.get("value");
                urlList.add(value);
            }
        }
        return urlList;
    }

    private List<String> getCoverImages(Short type,List<String> images,List<String> contentImages){
        //自动布局
        if(type==-1){
            //判断内容图数量
            int size = contentImages.size();
            //有几张取几张
            if(size>=3){
               return contentImages.subList(0, 2);
            }else if(size==2){
               return contentImages.subList(0, 1);
            }else if(size==1){
                ArrayList<String> list = new ArrayList<>();
                list.add(contentImages.get(0));
                return list;
            }else{
                return new ArrayList<>();
            }

        }else{
            return images;
        }
    }

    @Transactional(rollbackFor = RuntimeException.class)//事务回滚
    public Boolean addMaterial(Integer newsId,List<String> imageList,Integer type){
        if(CollectionUtils.isEmpty(imageList)){
            return true;
        }
        for (String url : imageList) {
            if (StringUtils.isEmpty(url)) {
                continue;
            }
            WmMaterial material = new WmMaterial();
            material.setUserId(UserThreadLocal.get().getId());
            material.setUrl(url);
            material.setType((short) 0);
            material.setIsCollection((short) 0);
            material.setCreatedTime(new Date());
            int insertResult = wmMaterialMapper.insert(material);
            if(insertResult<1){
                throw new RuntimeException("素材添加失败");
            }

            WmNewsMaterial newsMaterial = new WmNewsMaterial();
            newsMaterial.setType(type.shortValue());
            newsMaterial.setOrd((short) 1);
            newsMaterial.setNewsId(newsId);
            newsMaterial.setMaterialId(material.getId());
            int insertResult2 = wmNewsMaterialMapper.insert(newsMaterial);
            if(insertResult2<1){
                throw new RuntimeException("素材关系添加失败");
            }
        }
        return true;
    }

    private ArticleDto wmNews2ArticleDto(WmNews wmNews){
        if (wmNews==null) {
            return null;
        }
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews,articleDto);
        articleDto.setLayout(wmNews.getType());
        //查询渠道的名称
        Integer channelId = wmNews.getChannelId();
        if (channelId!=null) {
            WmChannel channel = wmChannelMapper.selectById(channelId);
            if(channel!=null){
                articleDto.setAuthorName(channel.getName());
            }
        }
        //查询作者的名称
        Integer userId = wmNews.getUserId();
        if(userId!=null){
            WmUser wmUser = wmUserMapper.selectById(userId);
            if(wmUser!=null){
                articleDto.setAuthorId(userId.longValue());
                articleDto.setAuthorName(wmUser.getName());
            }
        }
        return articleDto;
    }

}
